package bll

import (
	"context"
	"manager/client/grpc"
	log "manager/collector/logger"
	"manager/errors"
	"manager/event"
	"manager/model"
	"manager/model/entity"
	"manager/store"
	"manager/store/postgres"
	"manager/utils"
	"proto/dto"
	"time"

	"manager/auth"
)

type shareEbike struct {
	iShareEbike store.IShareEbike
	iEbike      store.IEbike
	iEbikeType  store.IEbikeType
	IUserEbike  store.IUserEbike
}

var ShareEbike = &shareEbike{
	iShareEbike: postgres.ShareEbike,
	iEbike:      postgres.Ebike,
	iEbikeType:  postgres.EbikeType,
	IUserEbike:  postgres.UserEbike,
}

func (a *shareEbike) init() func() {
	return func() {}
}

func (a *shareEbike) onEvent(data *event.Data) {
	if data == nil || (data.Type != event.Event_UnBind_Bike) {
		return
	}

	log.Info("---------------- shareEbike onEvent data:", utils.ToJsonString(data))
	if event.Event_UnBind_Bike == data.Type {
		// 解析参数
		obj := data.Data.(*event.UnBindBike)
		if obj == nil {
			log.Error("shareEbike onEvent err")
			return
		}

		// 参数校验
		if obj.BikeId == 0 || obj.UserId == 0 {
			log.Errorf("shareEbike onEvent params error userId:%v bikeId:%v", obj.UserId, obj.BikeId)
			return
		}

		// 列表
		_, list, _ := postgres.ShareEbike.List(context.Background(), &model.ShareEbikeListRequest{
			Index:       1,
			Size:        100,
			EbikeId:     &obj.BikeId,
			ShareUserId: &obj.UserId,
		})

		if len(list) == 0 {
			return
		}

		for i := 0; i < len(list); i++ {
			// 删除
			a.Delete(context.Background(), &model.ShareEbikeDeleteRequest{
				Id: list[i].Id,
			})
		}
	}
}

// Create 创建
func (a *shareEbike) Create(ctx context.Context, in *model.ShareEbikeCreateRequest) error {
	var (
		err          error
		ebikeEty     *entity.Ebike
		ebikeTypeEty *entity.EbikeType
		shareCount   int
	)
	// 获取用户Id
	in.UserId, _ = auth.ContextUserID(ctx)

	// 判断用户是不是车主
	b := UserEbike.IsManager(in.UserId, in.EbikeId)
	if !b {
		return errors.EbikeNotPermission.Error()
	}

	// 被分享人用户ID
	shareUser, err := grpc.UCmd.UserInfo(ctx, &dto.UserInfoRequest{
		Phone: in.Phone,
	})
	if err != nil {
		return err
	}

	// 分享的车是不是自己的
	if in.UserId == shareUser.Id {
		return errors.EbikeCannotSharedOneself.Error()
	}
	// 判断 车辆和分享的手机号在里面是否存在
	shareCount, _, err = a.iShareEbike.List(ctx, &model.ShareEbikeListRequest{
		EbikeId: &in.EbikeId,
		Phone:   &in.Phone,
	})

	if shareCount > 0 {
		return errors.EbikeAlreadyShared.Error()
	}

	// 调用user
	outInfo, err := grpc.UCmd.UserInfo(ctx, &dto.UserInfoRequest{
		Phone: in.Phone,
	})
	if err != nil {
		log.Error(err)
		return err
	}

	if outInfo.Id == 0 {
		return errors.EbikeShareUserNotFoundErr.Error()
	}

	// 查询车辆信息
	ebikeEty, err = a.iEbike.Find(ctx, in.EbikeId)
	if err != nil {
		log.Error(err)
		return err
	}

	in.Name = ebikeEty.Name
	in.Status = int(model.ShareWait)

	// 查询车型信息
	ebikeTypeEty, err = a.iEbikeType.Find(ebikeEty.TypeID)
	if err != nil {
		log.Error(err)
		return err
	}
	// 构建创建现场数据
	c := buildShareEbike(in)
	c.Photo = ebikeTypeEty.Image
	c.ShareUserId = outInfo.Id // 分享用户ID
	_, err = a.iShareEbike.Create(ctx, c)
	return err
}

// Update 更新
func (a *shareEbike) Update(ctx context.Context, in *model.ShareEbikeUpdateRequest) error {
	var (
		dict = make(map[string]interface{})
	)

	if in.UserId != nil {
		dict["user_id"] = *in.UserId
	}

	if in.EbikeId != nil {
		dict["ebike_id"] = *in.EbikeId
	}

	if in.ShareUserId != nil {
		dict["share_user_id"] = *in.ShareUserId
	}

	if in.Phone != nil {
		dict["phone"] = *in.Phone
	}

	if in.Name != nil {
		dict["name"] = *in.Name
	}

	if in.ShareTime != nil {
		dict["share_time"] = *in.ShareTime
	}

	if in.Status != nil {
		dict["status"] = *in.Status
	}

	dict["updated_at"] = time.Now().Unix()

	return a.iShareEbike.Update(ctx, in.Id, dict)
}

// Delete 删除
func (a *shareEbike) Delete(ctx context.Context, in *model.ShareEbikeDeleteRequest) error {
	var (
		err error

		ety         *entity.ShareEbike
		userBikeEty *entity.UserEbike
	)

	//查询该车辆分享信息
	ety, err = a.iShareEbike.Find(ctx, in.Id)
	if err != nil {
		log.Error(err)
		return err
	}

	// 判断分享状态，如果未接受的直接删除
	if ety.Status != int(model.ShareOk) {
		err = a.iShareEbike.Delete(ctx, in.Id)
		if err != nil {
			log.Error(err)
			return err
		}
		return err
	}

	//用户删除下面车辆
	no := int(model.IsManagerNo)

	userBikeEty, err = a.IUserEbike.FindByParameter(ctx, &model.UserEbikeRequest{
		UserID:    &ety.ShareUserId,
		EbikeID:   &ety.EbikeId,
		IsManager: &no,
	})

	if err != nil {
		log.Error(err)
		return err
	}
	err = a.iShareEbike.ExecTransaction(ctx, func(ctx context.Context) error {
		// 删除车辆绑定表数据
		err = a.IUserEbike.Delete(ctx, userBikeEty.ID)
		if err != nil {
			log.Error(err)
			return err
		}
		// 删除车辆表数据
		err = a.iShareEbike.Delete(ctx, in.Id)
		if err != nil {
			log.Error(err)
			return err
		}
		return nil
	})

	return err
}

// List 列表查询
func (a *shareEbike) List(ctx context.Context, in *model.ShareEbikeListRequest) (*model.ShareEbikeListResponse, error) {
	var (
		err    error
		total  int
		list   []*entity.ShareEbike
		out    = &model.ShareEbikeListResponse{}
		dtoEty *dto.UserListInfoResponse
		query  = &model.ShareEbikeListRequest{}
	)
	// 过滤状态
	in.FilterStatus = []int{int(model.ShareExpire)}

	UserID, _ := auth.ContextUserID(ctx)
	in.Size, in.Index = utils.PageUtil(in.Size, in.Index)
	// 主动分享用户查询
	if in.Type != nil && *in.Type == int(model.ShareTypeUser) {
		query.UserId = &UserID
	}

	// 被分享用户车辆列表查询
	if in.Type != nil && *in.Type == int(model.ShareTypeShareUser) {
		query.ShareUserId = &UserID
	}
	if in.EbikeId != nil {
		query.EbikeId = in.EbikeId
	}
	if total, list, err = a.iShareEbike.List(ctx, query); err != nil {
		return nil, err
	}

	if len(list) == 0 {
		return out, err
	}

	// 过滤过期的分享
	var newList []*entity.ShareEbike
	var expireShareIds []int64
	for j := 0; j < len(list); j++ {
		if list[j].ShareTime > 0 && list[j].AcceptedAt > 0 &&
			list[j].ShareTime+list[j].AcceptedAt < time.Now().Unix() {
			list[j].Status = int(model.ShareExpire)
			expireShareIds = append(expireShareIds, list[j].Id)
			continue
		}

		// 定义数据
		customData := UserEbike.GetBikeCustomData(UserID, list[j].EbikeId)
		list[j].Name = customData.Name
		list[j].Photo = customData.Image

		newList = append(newList, list[j])
	}

	list = newList

	ids := make([]int64, len(list))
	// 用户查寻分享给谁的车辆
	if *in.Type == int(model.ShareTypeUser) {
		for i, e := range list {
			ids[i] = e.ShareUserId
		}
	}
	// 分享用户查询谁分享给他的
	if *in.Type == int(model.ShareTypeShareUser) {
		for i, e := range list {
			ids[i] = e.UserId
		}
	}

	out.Total = total
	out.List = model.ShareEbikesEntityToDto(list)

	// 查询用户信息
	dtoEty, err = grpc.UCmd.UserListInfo(ctx, &dto.UserListInfoRequest{Ids: ids})
	if err != nil {
		log.Errorf("shareEbike err:%v", err)
	}

	if dtoEty != nil {
		for _, dtor1 := range dtoEty.List {
			for i2, l1 := range out.List {
				if *in.Type == int(model.ShareTypeUser) {
					if l1.ShareUserId == dtor1.Id {
						out.List[i2].UserName = dtor1.Name
					}
				}
				if *in.Type == int(model.ShareTypeShareUser) {
					if l1.UserId == dtor1.Id {
						out.List[i2].UserName = dtor1.Name
					}
				}
			}
		}
	}

	// 更新分享状态
	if len(expireShareIds) > 0 {
		postgres.GetDB(ctx).Model(&entity.ShareEbike{}).Where("id in (?)", expireShareIds).Update("status", int(model.ShareExpire))
	}

	return out, nil
}

// GetEffectiveShareEbike 查询有效的被分享的车辆
func (a *shareEbike) GetEffectiveShareEbike(ctx context.Context, userId int64, bikeIds []int64) (effectIds, expireIds map[int64]struct{}, err error) {

	effectIds = make(map[int64]struct{})
	expireIds = make(map[int64]struct{})

	// 查询有效的分享车辆
	_, list, _ := a.iShareEbike.List(ctx, &model.ShareEbikeListRequest{
		ShareUserId: &userId,
		BikeIds:     bikeIds,
	})

	for i := 0; i < len(list); i++ {
		if list[i].ShareTime > 0 && list[i].AcceptedAt > 0 && list[i].ShareTime+list[i].AcceptedAt < time.Now().Unix() {
			expireIds[list[i].EbikeId] = struct{}{}
			continue
		}

		effectIds[list[i].EbikeId] = struct{}{}
	}

	return
}

// ShareList 列表查询
func (a *shareEbike) ShareList(ctx context.Context, in *model.ShareAllRequest) (*model.ShareEbikeListAllResponse, error) {
	var (
		err error

		list     []*entity.ShareEbike
		infoList []*model.ShareEbikeInfo
		out      = &model.ShareEbikeListAllResponse{}
		dtoEty   *dto.UserListInfoResponse
		query    = &model.ShareEbikeListRequest{}
	)

	UserID, _ := auth.ContextUserID(ctx)
	in.Size, in.Index = utils.PageUtil(in.Size, in.Index)
	query.UserId = &UserID

	// 查询分享车辆信息
	all, err := a.iShareEbike.ShareAll(ctx, UserID)
	for i := 0; i < len(all); i++ {
		customData := UserEbike.GetBikeCustomData(UserID, all[i].ID)
		all[i].Name = customData.Name
		all[i].Photo = customData.Image
	}

	if err != nil {
		log.Error(err)
		return nil, err
	}
	if len(all) == 0 {
		return out, err
	}
	//设置总数
	out.Total = len(all)

	// 查询分享用户信息
	if _, list, err = a.iShareEbike.List(ctx, query); err != nil {
		return nil, err
	}

	if len(list) == 0 {
		return nil, err
	}

	ids := make([]int64, len(list))
	// 用户查寻分享给谁的车辆
	for i, e := range list {
		ids[i] = e.ShareUserId
	}

	// 查询用户信息
	dtoEty, err = grpc.UCmd.UserListInfo(ctx, &dto.UserListInfoRequest{Ids: ids})
	if err != nil {
		log.Error("-----Share List query-------", err)
		return nil, err
	}

	infoList = model.ShareEbikesEntityToDto(list)

	for _, dtor1 := range dtoEty.List {
		for j, l1 := range infoList {
			if l1.ShareUserId == dtor1.Id {
				infoList[j].UserName = dtor1.Name
			}
		}
	}

	for i, allInfo := range all {
		for _, l := range infoList {
			if allInfo.ID == l.EbikeId {
				if l.ShareTime > 0 && l.AcceptedAt > 0 && l.ShareTime+l.AcceptedAt < time.Now().Unix() {
					continue
				}

				all[i].ShareUserList = append(all[i].ShareUserList, l)
				allInfo.Count += 1
			}
		}
	}

	out.List = all
	return out, nil
}

// Accept 接受分享
func (a *shareEbike) Accept(ctx context.Context, in *model.ShareEbikeBaseRequest) error {
	var (
		err           error
		shareEbikeEty *entity.ShareEbike
		updateMap     = make(map[string]interface{}, 0)
	)
	// 查询分享信息
	shareEbikeEty, err = a.iShareEbike.Find(ctx, in.Id)
	if err != nil {
		log.Error(err)
		return err
	}

	// 执行事务
	err = a.iShareEbike.ExecTransaction(ctx, func(ctx context.Context) error {
		//创建车辆绑定信息
		_, err = a.IUserEbike.Create(ctx, &entity.UserEbike{
			UserID:    shareEbikeEty.ShareUserId,
			EbikeID:   shareEbikeEty.EbikeId,
			ShareTime: shareEbikeEty.ShareTime,
			IsManager: int(model.IsManagerNo),
			Photo:     shareEbikeEty.Photo,
			CreatedAt: time.Now().Unix(),
			UpdatedAt: time.Now().Unix(),
		})
		if err != nil {
			log.Error(err)
			return err
		}
		//修改分享车辆状态
		updateMap["status"] = int(model.ShareOk)
		updateMap["updated_at"] = time.Now().Unix()
		updateMap["accepted_at"] = time.Now().Unix()
		err = a.iShareEbike.Update(ctx, in.Id, updateMap)
		if err != nil {
			log.Error(err)
			return err
		}

		// 发送车辆绑定车主事件
		event.Emit(&event.Data{
			Type: event.Event_Bind_Bike,
			Data: &event.BindBike{
				BikeId: shareEbikeEty.EbikeId,
				UserId: shareEbikeEty.ShareUserId,
			},
		})
		return nil
	})
	return err
}

// buildShareEbike 构建创建数据现场
func buildShareEbike(in *model.ShareEbikeCreateRequest) *entity.ShareEbike {
	// todo: check the entity is required
	return &entity.ShareEbike{

		UserId: in.UserId,

		EbikeId: in.EbikeId,

		ShareUserId: in.ShareUserId,

		Phone: in.Phone,

		Name: in.Name,

		ShareTime: in.ShareTime,

		Status: in.Status,

		CreatedAt: time.Now().Unix(),

		UpdatedAt: time.Now().Unix(),
	}
}
